home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mint110s / util.c < prev    next >
C/C++ Source or Header  |  1993-09-14  |  13KB  |  654 lines

  1. /*
  2. Copyright 1990,1991,1992 Eric R. Smith.
  3. Copyright 1992,1993 Atari Corporation.
  4. All rights reserved.
  5. */
  6.  
  7. /*
  8.  * misc. utility routines
  9.  */
  10.  
  11. #include "mint.h"
  12.  
  13. /*
  14.  * given an address, find the corresponding memory region in this program's
  15.  * memory map
  16.  */
  17.  
  18. MEMREGION *
  19. addr2mem(a)
  20.     virtaddr a;
  21. {
  22.     int i;
  23.  
  24.     for (i = 0; i < curproc->num_reg; i++) {
  25.         if (a == curproc->addr[i])
  26.             return curproc->mem[i];
  27.     }
  28.     return 0;
  29. }
  30.  
  31. /*
  32.  * given a pid, return the corresponding process
  33.  */
  34.  
  35. PROC *
  36. pid2proc(pid)
  37.     int pid;
  38. {
  39.     PROC *p;
  40.  
  41.     for (p = proclist; p; p = p->gl_next) {
  42.         if (p->pid == pid)
  43.             return p;
  44.     }
  45.     return 0;
  46. }
  47.  
  48. /*
  49.  * return a new pid
  50.  */
  51.  
  52. int
  53. newpid()
  54. {
  55.     static int _maxpid = 1;
  56.     int i;
  57. #ifndef NDEBUG
  58.     int j = 0;
  59. #endif
  60.  
  61.     do {
  62.         i = _maxpid++;
  63.         if (_maxpid >= 1000) _maxpid = 1;
  64.         assert(j++ < 1000);
  65.     } while (pid2proc(i));
  66.  
  67.     return i;
  68. }
  69.  
  70. /*
  71.  * zero out a block of memory, quickly; the block must be word-aligned,
  72.  * and should be long-aligned for speed reasons
  73.  */
  74.  
  75. void
  76. zero(place, size)
  77.     char *place;
  78.     long size;
  79. {
  80.     long cruft;
  81.     long blocksize;
  82.  
  83.     cruft = size % 256;    /* quickzero does 256 byte blocks */
  84.     blocksize = size/256;    /* divide by 256 */
  85.     if (blocksize > 0) {
  86.         quickzero(place, blocksize);
  87.         place += (blocksize*256);
  88.     }
  89.     while (cruft > 0) {
  90.         *place++ = 0;
  91.         cruft--;
  92.     }
  93. }
  94.  
  95. #ifdef JUNK_MEM
  96. void
  97. fillwjunk(place, size)
  98.     long *place;
  99.     long size;
  100. {
  101.     while (size > 0) {
  102.         *place++ = size;
  103.         size -= 4;
  104.     }
  105. }
  106. #endif
  107.  
  108. /*
  109.  * kernel memory allocation routines
  110.  */
  111.  
  112. #define KERMEM_THRESHOLD (QUANTUM-8)
  113. #if 0
  114. #define KERMEM_SIZE QUANTUM
  115. #else
  116. #define KERMEM_SIZE ((KERMEM_THRESHOLD+8)*2)
  117. #endif
  118. #define KMAGIC ((MEMREGION *)0x87654321L)
  119. #define NKMAGIC 0x19870425L
  120.  
  121. void * ARGS_ON_STACK 
  122. kmalloc(size)
  123.     long size;
  124. {
  125.     MEMREGION *m;
  126.     MEMREGION **p;
  127.     long *lp;
  128.  
  129.     /*
  130.      * increase size by two pointers' worth: the first contains
  131.      * a pointer to the region descriptor for this block, and the
  132.      * second contains KMAGIC.  If the block came from nalloc,
  133.      * then they both contain NKMAGIC.
  134.      */
  135.     size += sizeof(m) + sizeof(m);
  136. /*
  137.  * for small requests, we use nalloc first
  138.  */
  139. tryagain:
  140.     if (size < KERMEM_THRESHOLD) {
  141.         lp = nalloc(size);
  142.         if (lp) {
  143.         *lp++ = NKMAGIC;
  144.         *lp++ = NKMAGIC;
  145.         TRACELOW(("kmalloc(%lx) -> (nalloc) %lx",size,lp));
  146.         return lp;
  147.         }
  148.         else {
  149.         DEBUG(("kmalloc(%lx): nalloc is out of memory",size));
  150.  
  151.     /* If this is commented out, then we fall through to try_getregion */
  152.         if (0 == (m = get_region(alt, KERMEM_SIZE, PROT_S))) {
  153.             if (0 == (m = get_region(core, KERMEM_SIZE, PROT_S))) {
  154.             DEBUG(("No memory for another arena"));
  155.             goto try_getregion;
  156.             }
  157.         }
  158.         lp = (long *)m->loc;
  159.         *lp++ = (long)KMAGIC;
  160.         *lp++ = (long)m;
  161. #if 0
  162.         nalloc_arena_add((void *)lp,KERMEM_SIZE - 2*SIZEOF(long));
  163. #else
  164.         nalloc_arena_add((void *)lp,KERMEM_SIZE);
  165. #endif
  166.         goto tryagain;
  167.         }
  168.     }
  169.  
  170. try_getregion:
  171.     m = get_region(alt, size, PROT_S);
  172.  
  173.     if (!m) m = get_region(core, size, PROT_S);
  174.  
  175.     if (m) {
  176.         p = (MEMREGION **)m->loc;
  177.         *p++ = KMAGIC;
  178.         *p++ = m;
  179.         TRACELOW(("kmalloc(%lx) -> (get_region) %lx",size,p));
  180.         return (void *)p;
  181.     }
  182.     else {
  183.         TRACELOW(("kmalloc(%lx) -> (fail)",size));
  184. #if 0
  185.         /* this is a serious offense; I want to hear about it */
  186.         /* maybe Allan wanted to hear about it, but ordinary users
  187.          * won't! -- ERS
  188.          */
  189.         NALLOC_DUMP();
  190.         BIG_MEM_DUMP(0,0);
  191. #endif
  192.         return 0;
  193.     }
  194. }
  195.  
  196. /* allocate from ST memory only */
  197.  
  198. void *
  199. kcore(size)
  200.     long size;
  201. {
  202.     MEMREGION *m;
  203.     MEMREGION **p;
  204.  
  205.     size += sizeof(m) + sizeof (m);
  206.     m = get_region(core, size, PROT_S);
  207.  
  208.     if (m) {
  209.         p = (MEMREGION **)m->loc;
  210.         *p++ = KMAGIC;
  211.         *p++ = m;
  212.         return (void *)p;
  213.     }
  214.     else {
  215.         return 0;
  216.     }
  217. }
  218.  
  219. void ARGS_ON_STACK 
  220. kfree(place)
  221.     void *place;
  222. {
  223.     MEMREGION **p;
  224.     MEMREGION *m;
  225.  
  226.     TRACELOW(("kfree(%lx)",place));
  227.  
  228.     if (!place) return;
  229.     p = place;
  230.     p -= 2;
  231.     if (*p == (MEMREGION *)NKMAGIC) {
  232.         nfree(p);
  233.         return;
  234.     }
  235.     else if (*p++ != KMAGIC) {
  236.         FATAL("kfree: memory not allocated by kmalloc");
  237.     }
  238.     m = *p;
  239.     if (--m->links != 0) {
  240.         FATAL("kfree: block has %d links", m->links);
  241.     }
  242.     free_region(m);
  243. }
  244.  
  245. /*
  246.  * "user" memory allocation routines; the kernel can use these to
  247.  * allocate/free memory that will be attached in some way to a process
  248.  * (and freed automatically when the process exits)
  249.  */
  250. void * ARGS_ON_STACK 
  251. umalloc(size)
  252.     long size;
  253. {
  254.     return (void *)m_xalloc(size, 3);
  255. }
  256.  
  257. void ARGS_ON_STACK 
  258. ufree(block)
  259.     void *block;
  260. {
  261.     (void)m_free((virtaddr)block);
  262. }
  263.  
  264. /*
  265.  * convert a time in milliseconds to a GEMDOS style date/time
  266.  * timeptr[0] gets the time, timeptr[1] the date.
  267.  * BUG/FEATURE: in the conversion, it is assumed that all months have
  268.  * 30 days and all years have 360 days.
  269.  */
  270.  
  271. void ARGS_ON_STACK 
  272. ms_time(ms, timeptr)
  273.     ulong ms;
  274.     short *timeptr;
  275. {
  276.     ulong secs;
  277.     short tsec, tmin, thour;
  278.     short tday, tmonth, tyear;
  279.  
  280.     secs = ms / 1000;
  281.     tsec = secs % 60;
  282.     secs /= 60;        /* secs now contains # of minutes */
  283.     tmin = secs % 60;
  284.     secs /= 60;        /* secs now contains # of hours */
  285.     thour = secs % 24;
  286.     secs /= 24;        /* secs now contains # of days */
  287.     tday = secs % 30;
  288.     secs /= 30;
  289.     tmonth = secs % 12;
  290.     tyear = secs / 12;
  291.     *timeptr++ = (thour << 11) | (tmin << 5) | (tsec >> 1);
  292.     *timeptr = (tyear << 9) | ((tmonth + 1) << 5) | (tday+1);
  293. }
  294.  
  295. /*
  296.  * unixtim(time, date): convert a Dos style (time, date) pair into
  297.  * a Unix time (seconds from midnight Jan 1., 1970)
  298.  */
  299.  
  300. static int
  301. mth_start[13] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
  302.  
  303. long ARGS_ON_STACK 
  304. unixtim(time, date)
  305.     unsigned time, date;
  306. {
  307.     int sec, min, hour;
  308.     int mday, mon, year;
  309.     long y, s;
  310.  
  311.     sec = (time & 31) << 1;
  312.     min = (time >> 5) & 63;
  313.     hour = (time >> 11) & 31;
  314.     mday = date & 31;
  315.     mon = ((date >> 5) & 15) - 1;
  316.     year = 80 + ((date >> 9) & 255);
  317.  
  318. /* calculate tm_yday here */
  319.     y = (mday - 1) + mth_start[mon] + /* leap year correction */
  320.         ( ( (year % 4) != 0 ) ? 0 : (mon > 1) );
  321.  
  322.     s = (sec) + (min * 60L) + (hour * 3600L) +
  323.         (y * 86400L) + ((year - 70) * 31536000L) +
  324.         ((year - 69)/4) * 86400L;
  325.  
  326.     return s;
  327. }
  328.  
  329. /* convert a Unix time into a DOS time. The longword returned contains
  330.    the time word first, then the date word.
  331.    BUG: we completely ignore any time zone information.
  332. */
  333. #define SECS_PER_MIN    (60L)
  334. #define SECS_PER_HOUR   (3600L)
  335. #define SECS_PER_DAY    (86400L)
  336. #define SECS_PER_YEAR   (31536000L)
  337. #define SECS_PER_LEAPYEAR (SECS_PER_DAY + SECS_PER_YEAR)
  338.  
  339. static int
  340. days_per_mth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  341.  
  342. long ARGS_ON_STACK 
  343. dostim(t)
  344.     long t;
  345. {
  346.         unsigned long time, date;
  347.     int tm_hour, tm_min, tm_sec;
  348.     int tm_year, tm_mon, tm_mday;
  349.     int i;
  350.  
  351.     if (t <= 0) return 0;
  352.  
  353.     tm_year = 70;
  354.     while (t >= SECS_PER_YEAR) {
  355.         if ((tm_year & 0x3) == 0) {
  356.             if (t < SECS_PER_LEAPYEAR)
  357.                 break;
  358.             t -= SECS_PER_LEAPYEAR;
  359.         } else {
  360.             t -= SECS_PER_YEAR;
  361.         }
  362.         tm_year++;
  363.     }
  364.     tm_mday = (int)(t/SECS_PER_DAY);
  365.         days_per_mth[1] = (tm_year & 0x3) ? 28 : 29;
  366.         for (i = 0; tm_mday >= days_per_mth[i]; i++)
  367.                 tm_mday -= days_per_mth[i];
  368.         tm_mon = i+1;
  369.     tm_mday++;
  370.         t = t % SECS_PER_DAY;
  371.         tm_hour = (int)(t/SECS_PER_HOUR);
  372.         t = t % SECS_PER_HOUR;
  373.         tm_min = (int)(t/SECS_PER_MIN);
  374.         tm_sec = (int)(t % SECS_PER_MIN);
  375.  
  376.     if (tm_year < 80) {
  377.         tm_year = 80;
  378.         tm_mon = tm_mday = 1;
  379.         tm_hour = tm_min = tm_sec = 0;
  380.     }
  381.  
  382.     time = (tm_hour << 11) | (tm_min << 5) | (tm_sec >> 1);
  383.     date = ((tm_year - 80) & 0x7f) << 9;
  384.     date |= ((tm_mon) << 5) | (tm_mday);
  385.     return (time << 16) | date;
  386. }
  387.  
  388. /*
  389.  * Case insensitive string comparison. note that this only returns
  390.  * 0 (match) or nonzero (no match), and that the returned value
  391.  * is not a reliable indicator of any "order".
  392.  */
  393.  
  394. int ARGS_ON_STACK 
  395. strnicmp(str1, str2, len)
  396.     register const char *str1, *str2;
  397.     register int len;
  398. {
  399.     register char c1, c2;
  400.  
  401.     do {
  402.         c1 = *str1++; if (isupper(c1)) c1 = tolower(c1);
  403.         c2 = *str2++; if (isupper(c2)) c2 = tolower(c2);
  404.     } while (--len >= 0 && c1 && c1 == c2);
  405.  
  406.     if (len < 0 || c1 == c2)
  407.         return 0;
  408.     return c1 - c2;
  409. }
  410.  
  411. int ARGS_ON_STACK 
  412. stricmp(str1, str2)
  413.     const char *str1, *str2;
  414. {
  415.     return strnicmp(str1, str2, 0x7fff);
  416. }
  417.  
  418.  
  419. /*
  420.  * string utilities: strlwr() converts a string to lower case, strupr()
  421.  * converts it to upper case
  422.  */
  423.  
  424. char * ARGS_ON_STACK 
  425. strlwr(s)
  426.     char *s;
  427. {
  428.     char c;
  429.     char *old = s;
  430.  
  431.     while ((c = *s) != 0) {
  432.         if (isupper(c)) {
  433.             *s = _tolower(c);
  434.         }
  435.         s++;
  436.     }
  437.     return old;
  438. }
  439.  
  440. char * ARGS_ON_STACK 
  441. strupr(s)
  442.     char *s;
  443. {
  444.     char c;
  445.     char *old = s;
  446.  
  447.     while ((c = *s) != 0) {
  448.         if (islower(c)) {
  449.             *s = _toupper(c);
  450.         }
  451.         s++;
  452.     }
  453.     return old;
  454. }
  455.  
  456. #ifdef OWN_LIB
  457.  
  458. /*
  459.  * Case sensitive comparison functions.
  460.  */
  461.  
  462. int
  463. strncmp(str1, str2, len)
  464.     register const char *str1, *str2;
  465.     register int len;
  466. {
  467.     register char c1, c2;
  468.  
  469.     do {
  470.         c1 = *str1++;
  471.         c2 = *str2++;
  472.     } while (--len >= 0 && c1 && c1 == c2);
  473.  
  474.     if (len < 0) return 0;
  475.  
  476.     return c1 - c2;
  477. }
  478.  
  479. int
  480. strcmp(str1, str2)
  481.     const char *str1, *str2;
  482. {
  483.     register char c1, c2;
  484.  
  485.     do {
  486.         c1 = *str1++;
  487.         c2 = *str2++;
  488.     } while (c1 && c1 == c2);
  489.  
  490.     return c1 - c2;
  491. }
  492.  
  493.  
  494. /*
  495.  * some standard string functions
  496.  */
  497.  
  498. char *
  499. strcat(dst, src)
  500.     char *dst;
  501.     const char *src;
  502. {
  503.     register char *_dscan;
  504.  
  505.     for (_dscan = dst; *_dscan; _dscan++) ;
  506.     while ((*_dscan++ = *src++) != 0) ;
  507.     return dst;
  508. }
  509.  
  510. char *
  511. strcpy(dst, src)
  512.     char *dst;
  513.     const char *src;
  514. {
  515.     register char *_dscan = dst;
  516.     while ((*_dscan++ = *src++) != 0) ;
  517.     return dst;
  518. }
  519.  
  520. char *
  521. strncpy(dst, src, len)
  522.     char *dst;
  523.     const char *src;
  524.     int len;
  525. {
  526.     register char *_dscan = dst;
  527.     while (--len >= 0 && (*_dscan++ = *src++) != 0)
  528.         continue;
  529.     while (--len >= 0)
  530.         *_dscan++ = 0;
  531.     return dst;
  532. }
  533.  
  534. int
  535. strlen(scan)
  536.     const char *scan;
  537. {
  538.     register const char *_start = scan+1;
  539.     while (*scan++) ;
  540.     return (int)((long)scan - (long)_start);
  541. }
  542.  
  543. /*
  544.  * strrchr: find the last occurence of a character in a string
  545.  */
  546. char *
  547. strrchr(str, which)
  548.     const char *str;
  549.     register int which;
  550. {
  551.     register unsigned char c, *s;
  552.     register char *place;
  553.  
  554.     s = (unsigned char *)str;
  555.     place = 0;
  556.     do {
  557.         c = *s++;
  558.         if (c == which)
  559.             place = (char *)s-1;
  560.     } while (c);
  561.     return place;
  562. }
  563.  
  564. unsigned char _ctype[256] =
  565. {
  566.     _CTc, _CTc, _CTc, _CTc,                /* 0x00..0x03 */
  567.     _CTc, _CTc, _CTc, _CTc,                /* 0x04..0x07 */
  568.     _CTc, _CTc|_CTs, _CTc|_CTs, _CTc|_CTs,        /* 0x08..0x0B */
  569.     _CTc|_CTs, _CTc|_CTs, _CTc, _CTc,        /* 0x0C..0x0F */
  570.  
  571.     _CTc, _CTc, _CTc, _CTc,                /* 0x10..0x13 */
  572.     _CTc, _CTc, _CTc, _CTc,                /* 0x14..0x17 */
  573.     _CTc, _CTc, _CTc, _CTc,                /* 0x18..0x1B */
  574.     _CTc, _CTc, _CTc, _CTc,                /* 0x1C..0x1F */
  575.  
  576.     _CTs, _CTp, _CTp, _CTp,                /* 0x20..0x23 */
  577.     _CTp, _CTp, _CTp, _CTp,                /* 0x24..0x27 */
  578.     _CTp, _CTp, _CTp, _CTp,                /* 0x28..0x2B */
  579.     _CTp, _CTp, _CTp, _CTp,                /* 0x2C..0x2F */
  580.  
  581.     _CTd|_CTx, _CTd|_CTx, _CTd|_CTx, _CTd|_CTx,    /* 0x30..0x33 */
  582.     _CTd|_CTx, _CTd|_CTx, _CTd|_CTx, _CTd|_CTx,    /* 0x34..0x37 */
  583.     _CTd|_CTx, _CTd|_CTx, _CTp, _CTp,        /* 0x38..0x3B */
  584.     _CTp, _CTp, _CTp, _CTp,                /* 0x3C..0x3F */
  585.  
  586.     _CTp, _CTu|_CTx, _CTu|_CTx, _CTu|_CTx,        /* 0x40..0x43 */
  587.     _CTu|_CTx, _CTu|_CTx, _CTu|_CTx, _CTu,        /* 0x44..0x47 */
  588.     _CTu, _CTu, _CTu, _CTu,                /* 0x48..0x4B */
  589.     _CTu, _CTu, _CTu, _CTu,                /* 0x4C..0x4F */
  590.  
  591.     _CTu, _CTu, _CTu, _CTu,                /* 0x50..0x53 */
  592.     _CTu, _CTu, _CTu, _CTu,                /* 0x54..0x57 */
  593.     _CTu, _CTu, _CTu, _CTp,                /* 0x58..0x5B */
  594.     _CTp, _CTp, _CTp, _CTp,                /* 0x5C..0x5F */
  595.  
  596.     _CTp, _CTl|_CTx, _CTl|_CTx, _CTl|_CTx,        /* 0x60..0x63 */
  597.     _CTl|_CTx, _CTl|_CTx, _CTl|_CTx, _CTl,        /* 0x64..0x67 */
  598.     _CTl, _CTl, _CTl, _CTl,                /* 0x68..0x6B */
  599.     _CTl, _CTl, _CTl, _CTl,                /* 0x6C..0x6F */
  600.  
  601.     _CTl, _CTl, _CTl, _CTl,                /* 0x70..0x73 */
  602.     _CTl, _CTl, _CTl, _CTl,                /* 0x74..0x77 */
  603.     _CTl, _CTl, _CTl, _CTp,                /* 0x78..0x7B */
  604.     _CTp, _CTp, _CTp, _CTc,                /* 0x7C..0x7F */
  605.  
  606.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80..0x8F */
  607.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90..0x9F */
  608.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0..0xAF */
  609.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0..0xBF */
  610.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0..0xCF */
  611.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0..0xDF */
  612.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0..0xEF */
  613.     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0  /* 0xF0..0xFF */
  614. };
  615.  
  616. int toupper(c)
  617.     int c;
  618. {
  619.     return(islower(c) ? (c ^ 0x20) : (c));
  620. }
  621.  
  622. int tolower(c)
  623.     int c;
  624. {
  625.     return(isupper(c) ? (c ^ 0x20) : (c));
  626. }
  627.  
  628. /*
  629.  * converts a decimal string to an integer
  630.  */
  631.  
  632. long
  633. atol(s)
  634.     const char *s;
  635. {
  636.     long d = 0;
  637.     int negflag = 0;
  638.     int c;
  639.  
  640.     while (*s && isspace(*s)) s++;
  641.     while (*s == '-' || *s == '+') {
  642.         if (*s == '-')
  643.             negflag ^= 1;
  644.         s++;
  645.     }
  646.     while ((c = *s++) != 0 && isdigit(c)) {
  647.         d = 10 * d + (c - '0');
  648.     }
  649.     if (negflag) d = -d;
  650.     return d;
  651. }
  652.  
  653. #endif /* OWN_LIB */
  654.